/**
 * @file main.cpp
 * @author AmorFati
 * @brief Lock-Demo
 * @version 0.1
 * @date 2022-03-04
 * @copyright Copyright (c) 2022
 * @remark ESP32-WROOM-32 GND连MOS负，12连MOS正;OPENMV P7连23，P4连RX0，GND，vin连3.3V一侧
 */

#include <Arduino.h>
#include <WiFi.h>
// #include <Wire.h>
#include <HTTPClient.h>
#include <string>
#include <stdbool.h>
#include <stdint.h>
// #include <PubSubClient.h>

extern "C"
{
#include <string.h>
#include <stdio.h>
// https://github.com/DaveGamble/cJSON
#include "cJSON.h"
}

// #define I2C_SDA GPIO_NUM_21
// #define I2C_SCL GPIO_NUM_22

// TwoWire I2CNF = TwoWire(0);

//无线设置
const char *ssid = "";
const char *password = "";

// host
#define HOST ""
// ssid
#define SSID ""

// lock
const int lock = GPIO_NUM_12;
// const int led = GPIO_NUM_13;
// register mode
const int regis = GPIO_NUM_23;

int IS_LOCK = 0;
int REMOTE_LOCK = 0;

//连接无线
void connectWiFi();
//检查网络状态
boolean checkWiFi();
//获取远程状态
void getStatus(int &status);
//更新远程状态
void updateStatus();

hw_timer_t *timer = NULL;
//定时器
static void IRAM_ATTR Timer0CallBack()
{
  getStatus(REMOTE_LOCK);
  if (REMOTE_LOCK==2)
  {
    pinMode(regis, OUTPUT);
    digitalWrite(regis, HIGH);
  }else{
    IS_LOCK = REMOTE_LOCK;
    printf("IS_LOCK: %d", IS_LOCK);
    printf("REMOTE_LOCK: %d", REMOTE_LOCK);
  }

}

void setup()
{
  // Wire.begin();
  Serial.begin(9600);
  pinMode(lock, OUTPUT);
  pinMode(regis, OUTPUT);
  connectWiFi();
  //设置定时器
  timer = timerBegin(0, 80, true);
  //回调函数
  timerAttachInterrupt(timer, Timer0CallBack, true);
  //单位us
  timerAlarmWrite(timer, 1000000, true);
  timerAlarmEnable(timer);
}

void loop()
{
  getStatus(REMOTE_LOCK);
  IS_LOCK = REMOTE_LOCK;
  if (IS_LOCK == 1)
  {
    digitalWrite(lock, HIGH);
    // digitalWrite(led, HIGH);
    delay(200);
    digitalWrite(lock, LOW);
    // digitalWrite(led, LOW);
    IS_LOCK = 0;
    updateStatus();
  }

  // if (IS_LOCK==2)
  // {
  //   digitalWrite(regis, HIGH);
  //   IS_LOCK = 0;
  //   updateStatus();

  // }
  
  char rev;
  if (Serial.available())
  {
    rev = Serial.read();
    if (rev == 1)
    {
      IS_LOCK = 1;
      digitalWrite(lock, HIGH);
      // digitalWrite(led, HIGH);

      delay(200);
      digitalWrite(lock, LOW);
      // digitalWrite(led, LOW);
      IS_LOCK = 0;
    }
  }
  delay(1000);
}

void connectWiFi()
{
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED)
  {
    delay(500);
    Serial.print(".");
  }
  // station，连接到wifi
  WiFi.mode(WIFI_STA);
  //连接网络
  WiFi.begin(ssid, password);

  while (!WiFi.isConnected())
  {
    delay(500);
    Serial.print(".");
  }

  //打印基本信息
  Serial.println("WiFi connected!");
  Serial.print("mac Address: ");
  Serial.println(WiFi.macAddress());
  WiFi.setHostname("ESP32");
  Serial.print("HostName: ");
  Serial.println(WiFi.getHostname());
}

boolean checkWiFi()
{
  if (WiFi.status() == WL_CONNECTED)
  {
    return true;
  }
  else
  {
    return false;
  }
}

void getStatus(int &status)
{
  if (checkWiFi())
  {
    HTTPClient http;
    http.begin("http://" HOST "/lock/" SSID);
    int code = http.GET();
    if (code > 0)
    {
      String payload = http.getString();
      Serial.println(code);
      Serial.println(payload);
      cJSON *root = cJSON_Parse(payload.c_str());
      if (root == NULL)
      {
        return;
      }
      cJSON *item;
      item = cJSON_GetObjectItem(root, "result");
      cJSON *s = cJSON_GetObjectItem(item, "status");
      status = s->valueint;
      cJSON_Delete(root);
      // printf("状态: %d\n", s->valueint);
    }
    else
    {
      Serial.println("Error on HTTP request");
    }
    http.end();
  }
}

void updateStatus()
{
  if (checkWiFi())
  {
    HTTPClient http;
    http.begin("http://" HOST "/lock");
    http.addHeader("Content-Type", "application/x-www-form-urlencoded");
    String s1(IS_LOCK);
    String httpRequestData = "id=" SSID "&status=" + s1;
    int code = http.PUT(httpRequestData);
    if (code > 0)
    {
      String payload = http.getString();
      Serial.println(code);
      Serial.println(payload);
      cJSON *root = cJSON_Parse(payload.c_str());
      if (root == NULL)
      {
        return;
      }
      cJSON *i;
      i = cJSON_GetObjectItem(root, "result");
      if (i->valueint == 1)
      {
        printf("update success\n");
      }
      cJSON_Delete(root);
    }
    else
    {
      Serial.println("Error on HTTP request");
    }
    http.end();
  }
}